import java.util.Arrays;

public class Practice {


    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,234,9,0,23};
        Arrays.sort(arr);
        System.out.println(Arrays.binarySearch(arr,23));
    }
    public static void main15(String[] args) {
        //深浅拷贝和拷贝的内容无关，只和拷贝的方式有关
        //深拷贝 -》 拷贝完改变拷贝数组的内容对原数组无影响
        //浅拷贝 -》 拷贝完改变拷贝数字的内容对原数组有影响
    }
    public static void main14(String[] args) {

        //三种拷贝方式
        int[] arr1 = {1,2,3,4};
        int[] arr2 = new int[arr1.length];
        //int[] arr3 = new int[arr1.length];
        arr2 = Arrays.copyOf(arr1,arr1.length);
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));
        arr2[0] = 111;
        System.out.println("__________________________");
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));

        System.arraycopy(arr1,0,arr2,0 ,arr2.length);
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));
        arr2[0] = 111;
        System.out.println("__________________________");
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));
        arr2 = arr1.clone();
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));
        arr2[0] = 111;
        System.out.println("__________________________");
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));

    }

    //由native修饰的方法是本地方法，特点：底层是
    //由C语言/cpp实现的，所以看不到具体实现代码，执行速度快

    public static void main13(String[] args) {
        int[] arr = {1,2,3,4};
        int[] arr1 = Arrays.copyOf(arr,arr.length*2);
        //可以当作扩容来用
        int[] ret = new int[arr.length];
        System.arraycopy(arr,0,ret ,0,arr.length);
        System.out.println(Arrays.toString(ret));
    }
    public static String myStringCopy(int[] arr) {
        String str = "";
        return str;
    }
    public static String myToString(int[] arr) {
        if(arr == null) {
            return "null";
        }
        String str = "[";
        for (int i = 0; i < arr.length; i++) {
            str = str + arr[i];
            if(i < arr.length - 1) {
                str = str + ",";
            }
        }
        str = str + "]";
        return str;
    }
    public static void main12(String[] args) {
        int[] arr = {1,2,3,4};
        System.out.println(myToString(arr));
    }

    public static int[] grow3(int[] arr) {
       int[] tmp = new int[arr.length];
       //不初始化，默认是0
        for(int i = 0;i < arr.length;i++) {
            tmp[i] = arr[i] * 2;
        }
        return tmp;
        //Java中允许数组的大小是变量，C语言必须是常量
    }
    public static void main10(String[] args) {
        int[] arr = {1,2,3,4};
        int[] ret = grow3(arr);
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(ret));
    }


    public static int[] grow(int[] arr) {
        for(int i = 0;i < arr.length;i++) {
            arr[i] = arr[i] * 2;
        }
        //已经对arr进行了修改（修改了实参指向的对象的值，实参指向对象已经被修改）
        //可以不需要返回值（类似于C语言的传址调用）
        return arr;
    }
    public static void main9(String[] args) {

        int[] arr = {1,2,3,4};
        int[] ret = grow(arr);
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(ret));

    }

    public static int[] fun10() {
        int[] tmp ={11,2,34};
        return tmp;
    }

    public static void main8(String[] args) {
        //总结
        //当数组作为参数的时候进行传递的时候，其实还是按值传递，只不过此时的值，是一个地址
        //那么就会出现两种情况
        //形参修改指向  arr=new int[]{1};
        //形参修改指向对象的值 arr[0]=9,此时才会影响实参
        //


        int[] arr = {1,2,3,45};
        int[] arr1 = fun10();
        System.out.println(Arrays.toString(arr1));



    }
    public static void func1(int[] arr){
        arr = new int[]{4,5,6};
    }
    public static void func2(int[] arr) {
        arr[0] = 999;
    }
    //此时传的是引用，我们通过引用修改了原来的值
    public static void main7(String[] args) {
        //数组的使用  保存数据
        int[] arr1 = {1,2,3,4};
        func1(arr1);
        System.out.println(Arrays.toString(arr1));
        func2(arr1);
        System.out.println(Arrays.toString(arr1));

    }
    public static void main6(String[] args) {
        //C语言中NULL指向的是0号地址，0号地址受保护的范围是受保护的，所以使用时会报错

        //Java中null和零号地址无关联，代表java不指向任何对象
    }
    public static void main5(String[] args) {
        int[] arr1 = {1,2,3,4};
        int[] arr2 = {11,22,33,44};
        arr1 = arr2;
        arr1[0] = 8888;
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));

        //原先arr1指向的对象如果没人引用，则系统自动回收arr1一开始指向的对象

        //现在两个引用指向同一个对象，通过其中任何一个引用修改这个
        //对象的值，另一个i引用去访问时，也是被修改后的对象


    }
    public static void main4(String[] args) {
        //再谈引用变量
        int[] array1 = {1,2,4,5};
        array1[0] = 99;
        int[] array2 = array1;
        array2[0] = 100;
        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(array2));
        //引用变量存的是数组的地址，当赋值时，赋值的是数组的地址，之后两个引用变量
        //同时指向同一个数组，两个变量可以同时操控数组





    }
    public static void mai3(String[] args) {
        int[] array = null;
        //System.out.println(array[0]);
        // 报错，出现空指针异常，根据提示找一个引用为什么是null
        //System.out.println(array.length);
        //System.out.println(array[0]);
        // 报错，出现空指针异常，(使用了一个值为null的引用)根据提示找一个引用为什么是null
        //null的作用和C语言的NULL类似，都是表示一个无效的内存位置，因此不能对这个内存进行任何读写操作，一旦尝试读写，就会抛出 NullPoniterExcepttion
        //java中没有约定null和0号地址的内存有任何关联

    }
    public static void main2(String[] args) {

        int[] arr = {1,2,3};
        int[] arr1 = new int[]{1,2,3,4};
        int[] arr2 = new int[10];
        //基本数据类型 引用类型
        //Java1虚拟机栈 本地方法栈 方法区 堆 程序计数器
        //局部变量存在栈上  arr/arr1/arr2
        //引用变量也存在栈上，引用变量存的是数组的首地址
        //arr这个引用指向一个对象

        //引用变量也是一个变量
        //局部变量就是在方法内部定义的变量，不要和引用变量混到一起
        //引用变量就是一个变量，用来存对象的地址

        int[] arr4 = {1,2,3,4};
        for (int x:arr4) {
            System.out.println(x);
        }
        //基本数据类型变量  通过基本数据类型定义的变量
        //引用类型变量    一般存的是对象的地址

        //int[] arr5 = null;
        //int a ;
        //此时arr4和a都是局部变量，Java中局部变量使用时必须初始化

        //null--》这个引用不指向任何对象，此时赋值null
        //




    }
    public static void main1(String[] args) {
//        //数组如果不默认初始化，都为0
//        //java虚拟机栈(栈)   保存局部变量
//        //本地方法栈
//        //方法区   存的是方法的变量
//        //堆                保存引用类型的变量
//        //程序计数器
//
//        int[] array = new int[10];
//        //array存放的是int【10】的地址，引用变量 就是一个存放地址的变量
//        //array 这个引用指向了一个 数组对象
//
//
//        //引用变量和局部变量都存在栈上吗？局部变量的内存是在栈上开辟的、对象是在堆上开辟的
//        //局部变量就是在方法内部创建的变量，不要和引用变量混在一起，这是两个不一样的概念
//
//
//        //基本数据类型 （8） 都是基本数据类型 通过基本数据类型定义的变量
//
//        int[] arr = new int[10];
//        System.out.println(arr[0]);
//
//        //java中，局部变量在使用时必须初始化,array在使用时如果不指向任何对象，则直接赋值NULL
//        //表明不指向任何数组
//
////        int[] arr1 = NULL;
////        System.out.println(arr[1]);
//        //空指针异常


//        int[] array1 = {1,2,3,4};
//        array1[0] = 99;
//        int[] array2 = array1;
//        //将array1指向的数组的地址赋值给array2
//        array2[0] = 100;
//        System.out.println(Arrays.toString(array1));
//        System.out.println(Arrays.toString(array2));

        int[] array1 = {1,2,3,4};
        int[] array2 = {1,2,3,4};
        array1 = array2;
        array1[0] = 1888;
        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(array2));

        //没有人引用的对象（Array1一开始指向的数组），就会被系统回收
        //Java不用free，Java有自动回收机制

        //两个引用同时指向了一个对象，所以当两个引用都指向同一个对象，通过其中
        //任何一个引用修改其中的值，另一个引用访问时也是会被改变的

        //


    }
}
